#include "SPL06.h"

iic_bus_struct spl06_iic_struct = {
	.IIC_SDA_PORT = GPIOB,
	.IIC_SCL_PORT = GPIOB,
	.IIC_SDA_PIN = GPIO_PIN_13,
	.IIC_SCL_PIN = GPIO_PIN_14
};

int16_t c0,c1,c01,c11,c20,c21,c30;
int32_t c00,c10;

void SPL06_Write_Byte(u8 reg, u8 data)
{
	myiic_send_one_byte(&spl06_iic_struct, SPL_ADDRESS, reg, data);
}

u8 SPL06_Read_Byte(u8 reg)
{
	u8 data;
	
	data = myiic_read_one_byte(&spl06_iic_struct, SPL_ADDRESS, reg);
	return data;

}

void SPL06_Set_Mode(u8 mode)
{
	if(mode == LOWPOWER)//5 Pa precision. 1 pr sec. 6 uA 
	{
//		SPL06_Write_Byte(SPL_PRS_CFG, 0x01);
//		SPL06_Write_Byte(SPL_TMP_CFG, 0x80);
		SPL06_Write_Byte(SPL_PRS_CFG, 0x01);		// Pressure 2x oversampling

		SPL06_Write_Byte(SPL_TMP_CFG, 0x80);		// External Temperature 1x oversampling

		SPL06_Write_Byte(SPL_MEAS_CFG, 0x07);	// continuous pressure and temperature measurement

		SPL06_Write_Byte(SPL_CFG_REG, 0x00);		//  
	}
	else if(mode == INDOOR)//10 cm precision. 2 pr sec. 30 uA
	{
		SPL06_Write_Byte(SPL_PRS_CFG, 0x14);
		SPL06_Write_Byte(SPL_TMP_CFG, 0x80);
	}
	else if(mode == SPORTS)//5 cm precision 4 pr sec. 200 uA
	{
		SPL06_Write_Byte(SPL_PRS_CFG, 0x26);
		SPL06_Write_Byte(SPL_TMP_CFG, 0xA0);
	}
}


u8 SPL06_Init(void)
{
	SPL_CLK_ENABLE;
	iic_dev_init(&spl06_iic_struct);
	
	SPL06_Set_Mode(LOWPOWER);
	
	c0 = get_c0();
	c1 = get_c1();
	c01 = get_c01();
	c11 = get_c11(); 
	c20 = get_c20();
	c21 = get_c21();
	c30 = get_c30();
	c00 = get_c00();
	c10 = get_c10();
	
	if(SPL06_Read_Byte(SPL_PRS_CFG)!=0x01 || SPL06_Read_Byte(SPL_CFG_REG)!=0x00)
	{return 1;}//ERRO
	else 
	{return 0;}//SUCCESS
}



u8 SPL06_ReadID(void)
{
	return SPL06_Read_Byte(SPL_ID_REG);
}


int32_t get_press(void)
{
	u8 arr[3] = {0};
	
	arr[0] = SPL06_Read_Byte(SPL_PRS_B2);	//high
	arr[1] = SPL06_Read_Byte(SPL_PRS_B1); //mid
	arr[2] = SPL06_Read_Byte(SPL_PRS_B0); //low
	
	int32_t praw = (arr[0] << 16) | (arr[1] << 8) | arr[2];
	
	if(praw & 0x00800000) praw|=0xFF000000;
	
	return praw;
}

int32_t get_temp(void)
{
	u8 arr[3] = {0};
	
	arr[0] = SPL06_Read_Byte(SPL_TMP_B2);	//high
	arr[1] = SPL06_Read_Byte(SPL_TMP_B1); //mid
	arr[2] = SPL06_Read_Byte(SPL_TMP_B0); //low
	
	int32_t traw = (arr[0] << 16) | (arr[1] << 8) | arr[2];
	
	if(traw & 0x00800000) traw|=0xFF000000;
	
	return traw;
}



int16_t get_c0(void)
{
	uint8_t buff[2];
	int16_t c0;
	buff[0] = SPL06_Read_Byte(COEF_C0);
	buff[1] = SPL06_Read_Byte(COEF_C0_C1);
	c0 = buff[0];
	c0 = (c0 << 4) | (buff[1] >> 4);
	if(c0 & (1<<11))
	{c0 |= 0xF000;}
	return c0;
}

int16_t get_c1(void)
{
	uint8_t buff[2];
	int16_t c1;
	buff[0] = SPL06_Read_Byte(COEF_C0_C1);
	buff[1] = SPL06_Read_Byte(COEF_C1);
	c1 = buff[0] & 0x0F;
	c1 = (c1 << 8) | buff[1] ;
	if(c1 & (1<<11))
	{c1 |= 0xF000;}
	return c1;
}

int32_t get_c00(void)
{
	uint8_t buff[3];
	int32_t c00;
	buff[0] = SPL06_Read_Byte(COEF_C00_H);
	buff[1] = SPL06_Read_Byte(COEF_C00_L);
	buff[2] = SPL06_Read_Byte(COEF_C00_C10);
	c00 = buff[0];
	c00 = c00<<8 | buff[1];
	c00 = (c00<<4) | (buff[2]>>4);
	if(c00 & (1<<19))
	{c00 |= 0xFFF00000;}
	return c00;
}

int32_t get_c10(void)
{
	uint8_t buff[3];
	int32_t c10;
	buff[0] = SPL06_Read_Byte(COEF_C00_C10);
	buff[1] = SPL06_Read_Byte(COEF_C10_M);
	buff[2] = SPL06_Read_Byte(COEF_C10_L);
	c10 = buff[0] & 0x0F;
	c10 = c10<<8 | buff[1];
	c10 = c10<<8 | buff[2];
	if(c10 & (1<<19))
	{c10 |= 0xFFF00000;}
	return c10;
}

int16_t get_c01(void)
{
	uint8_t buff[2];
	int32_t c01;
	buff[0] = SPL06_Read_Byte(COEF_C01_H);
	buff[1] = SPL06_Read_Byte(COEF_C01_L);
	c01 = buff[0];
	c01 = c01<<8 | buff[1];
	return c01;
}

int16_t get_c11(void)
{
	uint8_t buff[2];
	int32_t c11;
	buff[0] = SPL06_Read_Byte(COEF_C11_H);
	buff[1] = SPL06_Read_Byte(COEF_C11_L);
	c11 = buff[0];
	c11 = c11<<8 | buff[1];
	return c11;
}

int16_t get_c20(void)
{
	uint8_t buff[2];
	int32_t c20;
	buff[0] = SPL06_Read_Byte(COEF_C20_H);
	buff[1] = SPL06_Read_Byte(COEF_C20_L);
	c20 = buff[0];
	c20 = c20<<8 | buff[1];
	return c20;
}

int16_t get_c21(void)
{
	uint8_t buff[2];
	int32_t c21;
	buff[0] = SPL06_Read_Byte(COEF_C21_H);
	buff[1] = SPL06_Read_Byte(COEF_C21_L);
	c21 = buff[0];
	c21 = c21<<8 | buff[1];
	return c21;
}

int16_t get_c30(void)
{
	uint8_t buff[2];
	int32_t c30;
	buff[0] = SPL06_Read_Byte(COEF_C30_H);
	buff[1] = SPL06_Read_Byte(COEF_C30_L);
	c30 = buff[0];
	c30 = c30<<8 | buff[1];
	return c30;
}


float Altitude_Calculate(void)
{
	float Altitude;
	Altitude = 44330 * (1 - powf(Pressure_Calculate()/101325, 0.1903));
	return Altitude;
}


float Pressure_Calculate(void)
{
	float Traw_sc, Praw_sc, Pcomp;
	
	Traw_sc = get_temp();
	Traw_sc /= KT;
	Praw_sc = get_press();
	Praw_sc /= KP;
	Pcomp = (c00) + Praw_sc * ((c10) + Praw_sc * ((c20) + Praw_sc * (c30))) + Traw_sc * (c01) + Traw_sc * Praw_sc * ((c11) + Praw_sc * (c21));
	
	return Pcomp;
}


float Temperature_Calculate(void)
{
	float Traw_sc,Tcomp;
	
	Traw_sc = get_temp();
	Traw_sc /= KT;
	Tcomp =  c0 * 0.5 + c1 * Traw_sc;
	return Tcomp;
}


